package com.amado.course35Concurrent;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 *二、Condition
 *
 * Condition是在java 1.5中才出现的，它用来替代传统的Object的wait()、notify()实现线程间的协作，相比使用Object的wait()、notify()，
 * 使用Condition的await()、signal()这种方式实现线程间协作更加安全和高效。因此通常来说比较推荐使用Condition。
 * Condition类能实现synchronized和wait、notify搭配的功能，另外比后者更灵活，Condition可以实现多路通知功能，
 * 也就是在一个Lock对象里可以创建多个Condition（即对象监视器）实例，线程对象可以注册在指定的Condition中，从而可以有选择的进行线程通知
 * ，在调度线程上更加灵活。而synchronized就相当于整个Lock对象中只有一个单一的Condition对象，所有的线程都注册在这个对象上。线程开始notifyAll时，
 * 需要通知所有的WAITING线程，没有选择权，会有相当大的效率问题。
 *
 * 1、Condition是个接口，基本的方法就是await()和signal()方法。
 * 2、Condition依赖于Lock接口，生成一个Condition的基本代码是lock.newCondition()，参考下图。
 * 3、调用Condition的await()和signal()方法，都必须在lock保护之内，就是说必须在lock.lock()和lock.unlock之间才可以使用。
 * 4、Conditon中的await()对应Object的wait()，Condition中的signal()对应Object的notify()，Condition中的signalAll()对应Object的notifyAll()。
 * 接下来，使用Condition来实现等待/唤醒，并且能够唤醒制定线程。
 */
public class S09ReentrantLockConditionTest {
	private static final ReentrantLock lock = new ReentrantLock();

	public static void main(String[] args) throws InterruptedException {
		Condition condition = lock.newCondition();
		new Thread(()->{
			try {
				lock.lock();
				System.out.println("线程a lock");
				//wait方法先释放掉lock的锁，再调用pick方法锁住，signal会调用unpick方法解锁
				condition.await();
				System.out.println("线程a wait");
			} catch (Exception e) {
				e.printStackTrace();
			}finally {
				lock.unlock();
				System.out.println("线程a unlock");
			}
		}).start();
		Thread.sleep(2000);
		new Thread(()->{
			try {
				lock.lock();
				System.out.println("线程b lock");
				condition.signal();
				System.out.println("线程b await");
			}finally {
				lock.unlock();
				System.out.println("线程b unlock");
			}
		}).start();
	}
}
